package tesis.common.security.filter;


import tesis.common.utils.StringUtil;
import java.io.IOException;
import java.util.GregorianCalendar;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Este filtro solo realiza un auto login si se le pasan los parametros
 * adecuados por el URL. No realiza autenticacion, solo pasa las credenciales a
 * la capa inferior. Debe existir una capa inferior que haga la autenticacion y
 * control de autorizacion.
 *
 */
public class AutoLoginFilter implements Filter {

    private static Logger log = LoggerFactory.getLogger(AutoLoginFilter.class);
    private static final String PARAM_CHECK_CLIENT_IP = "checkClientIP";
    private static final String PARAM_CHECK_DATE = "checkDate";
    private static final String PARAM_INVALID_PARAM_PAGE = "invalidParamPage";
    private static final String URL_PARAM_SESSION = "session";
    private static final String URL_PARAM_CAD_ENC = "xxyyxxx";
    private static String invalidParamPage;
    private static boolean checkClientIP;
    private static boolean checkDate;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.debug("<<-------------------------- AutoLoginFilter - doFilter");
        boolean parametrosInvalidos = false;

        if (request instanceof HttpServletRequest) {
            request.setCharacterEncoding("UTF-8");
            HttpServletRequest httpRequest = (HttpServletRequest) request;

            String sessionId = request.getParameter(URL_PARAM_SESSION);
            String cadenaEnc = request.getParameter(URL_PARAM_CAD_ENC);
            String p_user = request.getParameter("p_usuario");
            String fromIntranet = request.getParameter("fromIntranet");
            log.debug("sessionId [{}] cadenaEnc [{}] p_user [{}] fromIntranet [{}]", new Object[]{sessionId, cadenaEnc, p_user, fromIntranet});

            if ((sessionId != null && !sessionId.equals("") && cadenaEnc != null && !cadenaEnc.equals("")) || (!StringUtil.isEmpty(p_user) && !StringUtil.isEmpty(sessionId) && !StringUtil.isEmpty(fromIntranet))) {
                HttpSession session = httpRequest.getSession();
                if (cadenaEnc != null) {
                    cadenaEnc = cadenaEnc.replaceAll(" ", "+");
                }

                try {
                    if (sessionId != null && !sessionId.equals("") && cadenaEnc != null && !cadenaEnc.equals("")) {
                        String cadenaDes = "";//EncripUtil.decrypt(sessionId, cadenaEnc);
                        log.debug("cadenaEnc [{}] cadenaDes [{}]", cadenaEnc, cadenaDes);

                        String j_ip = null;
                        String ipClient = null;
                        if (checkClientIP) {
                            j_ip = getIp(cadenaDes);
                            ipClient = request.getRemoteAddr();
                            log.debug("ipCliente " + ipClient);
                        }

                        String j_fecha = null;
                        String p_fecha = null;
                        if (checkDate) {
                            log.debug("checkDate:");
                            j_fecha = getFecha(cadenaDes);
                            log.debug("j_fecha:" + j_fecha);
                            p_fecha = getAAAMMDD();
                            log.debug("p_fecha:" + p_fecha);
                        }

                        if ((checkClientIP && !j_ip.equals(ipClient)) || (checkDate && !j_fecha.equals(p_fecha))) {
                            log.debug("parametros invalidos");
                            parametrosInvalidos = true;
                        } else {
                            String j_username = getUsername(cadenaDes);
                            log.debug("j_username=" + j_username);
//                            String j_password = getPassword(cadenaDes);
//                            log.debug("j_password="+j_password);
                            session.setAttribute("j_username", j_username);
//                            session.setAttribute("j_password", j_password);
                        }
                    } else if (!StringUtil.isEmpty(p_user) && !StringUtil.isEmpty(sessionId) && !StringUtil.isEmpty(fromIntranet)) {
                        session.setAttribute("j_username", p_user);
                        session.setAttribute("fromIntranet", ""/*EncripUtil.decrypt(sessionId, fromIntranet)*/);
                    }
                } catch (Exception e) {
                    log.debug("Error al obtener datos para autenticacion.", e);
                    session.setAttribute("j_username", null);
                    session.setAttribute("j_password", null);
                    parametrosInvalidos = true;
                }
            }
        }

        if (parametrosInvalidos && invalidParamPage != null) {
            //redirigir a una pagina de parametros invalidos
            log.debug("Redirigiendo a pagina de parametros invalidos.");
            request.getRequestDispatcher(invalidParamPage).forward(request, response);
        } else {
            chain.doFilter(request, response);
        }
    }

    @Override
    public void init(FilterConfig config) throws ServletException {
        checkClientIP = loadBooleanParameter(config, PARAM_CHECK_CLIENT_IP, false);
        checkDate = loadBooleanParameter(config, PARAM_CHECK_DATE, true);
        invalidParamPage = config.getInitParameter(PARAM_INVALID_PARAM_PAGE);
        log.debug("checkClientIP [{}] checkDate [{}] invalidParamPage [{}]", new Object[]{checkClientIP, checkDate, invalidParamPage});
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub
    }

    ////////////////////////////////////////////////////
    private boolean loadBooleanParameter(FilterConfig config, String parameterName, boolean defaultValue) {
        boolean result = defaultValue;
        String valueString = config.getInitParameter(parameterName);
        if (valueString != null) {
            if (valueString.equalsIgnoreCase("true")) {
                result = true;
            } else if (valueString.equalsIgnoreCase("false")) {
                result = false;
            } else {
                log.error("Error al leer el parametro " + parameterName + ". Deber ser true o false. Se utilizara el valor por defecto: " + defaultValue);
            }
        }
        return result;
    }

    private static String getFecha(String cadenaDes) {
        String pfecha = null;
        if (cadenaDes != null) {
            int index = cadenaDes.lastIndexOf("=");
            pfecha = cadenaDes.substring(index + 1);
        }
        return pfecha;
    }

    private static String getIp(String cadenaDes) {
        String ip = null;
        if (cadenaDes != null) {
            int index = cadenaDes.indexOf("&");
            cadenaDes = cadenaDes.substring(index + 1);
            ip = getPassword(cadenaDes);
        }
        return ip;
    }

    private static String getPassword(String cadenaDes) {
        String pwd = null;
        if (cadenaDes != null) {
            int indexIni = cadenaDes.indexOf("&");
            cadenaDes = cadenaDes.substring(indexIni + 1);
            pwd = getUsername(cadenaDes);
        }
        return pwd;
    }

    private static String getUsername(String cadenaDes) {
        String username = null;
        if (cadenaDes != null) {
            int index = cadenaDes.indexOf("=");
            int indexsep = cadenaDes.indexOf("&");
            username = cadenaDes.substring(index + 1, indexsep);

        }
        return username;
    }

    public static String getAAAMMDD() {
        return tesis.utils.DateUtil.formatDDMMYYYY(GregorianCalendar.getInstance().getTime());
    }
}
